package com.gzqylc.docker.extend.auth.utils;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.method.HandlerMethod;

import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Pattern;

@Slf4j
public class RequestTool {

    private static final int DEFAULT_HTTPS_PORT = 443;
    private static final int DEFAULT_HTTP_PORT = 80;

    /**
     * get请求
     * @param url
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String get(String url) throws ClientProtocolException, IOException {
        String returnData = null;
        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet(url);
        CloseableHttpResponse response = httpclient.execute(httpGet);
        try {
            HttpEntity entity = response.getEntity();
            returnData = EntityUtils.toString(entity);
            EntityUtils.consume(entity);
        } finally {
            if (response != null)
                response.close();
            httpclient.close();
        }
        return returnData;
    }

    /**
     * post获取数据
     * @param url
     * @param param
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String post(String url, Map<String, Object> param) throws ClientProtocolException, IOException {
        String returnData = null;
        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("Content-type","application/json;charset=utf-8");
        httpPost.setHeader("Accept", "application/json");

        JSONObject jsonObject = new JSONObject();
        if (null != param && param.size() > 0) {
            //List<NameValuePair> nvps = new ArrayList<NameValuePair>();
            // 通过map集成entrySet方法获取entity
            Set<Entry<String, Object>> entrySet = param.entrySet();
            // 循环遍历，获取迭代器
            Iterator<Entry<String, Object>> iterator = entrySet.iterator();
            while (iterator.hasNext()) {
                Entry<String, Object> mapEntry = iterator.next();
                jsonObject.put(mapEntry.getKey(), mapEntry.getValue());
            }
        }
        httpPost.setEntity(new StringEntity(jsonObject.toString(), Charset.forName("UTF-8")));

//        List<NameValuePair> nvps = new ArrayList<>();
//        for (Entry<String, Object> e : param.entrySet()) {
//            if (e.getValue() != null) {
//                nvps.add(new BasicNameValuePair(e.getKey(), e.getValue().toString()));
//            }
//        }
//        httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));

        CloseableHttpResponse response = httpclient.execute(httpPost);

        try {
            HttpEntity entity = response.getEntity();
            returnData = EntityUtils.toString(entity);
            EntityUtils.consume(entity);
        } finally {
            if (response != null)
                response.close();
            httpclient.close();
        }
        return returnData;
    }

    public static void downloadFile(File file, String fileName, HttpServletResponse response) throws IOException {
        response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
        response.setContentLengthLong(file.length());
        FileInputStream is = null;
        ServletOutputStream os = null;
        try {
            is = new FileInputStream(file);
            os = response.getOutputStream();
            IOUtils.copy(is, os);
        } finally {
            IOUtils.closeQuietly(is);
            IOUtils.closeQuietly(os);
        }
    }


    public static void dumpHeader(HttpServletRequest request) {
        Enumeration<String> headerNames = request.getHeaderNames();
        while ((headerNames.hasMoreElements())) {
            String headerName = headerNames.nextElement();
            String value = request.getHeader(headerName);
            log.info("header: {}={}", headerName, value);
        }
    }

    public static void dumpParameter(HttpServletRequest request) {
        Map<String, String[]> parameterMap = request.getParameterMap();
        for (Entry<String, String[]> e : parameterMap.entrySet()) {
            log.info("parameter: {}={}", e.getKey(), e.getValue());
        }
    }


    public static String getUrl(HttpServletRequest request) {
        String requestUri = request.getRequestURI();
        String contextPath = request.getContextPath();
        return requestUri.substring(contextPath.length());
    }

    public static String getFullUrl(HttpServletRequest request) {
        String url = getUrl(request);
        if (url.startsWith("/")) {
            url = url.substring(1);
        }
        return getBaseUrl(request) + url;
    }

    public static String getBaseUrl(HttpServletRequest request) {
        String path = request.getContextPath();

        return getOrigin(request) + path + "/";
    }

    public static String getOrigin(HttpServletRequest request) {
        String scheme = request.getScheme();
        int port = request.getServerPort();

        boolean skipPort = (scheme.equals("http") && port == DEFAULT_HTTP_PORT)
                || (scheme.equals("https") && port == DEFAULT_HTTPS_PORT);
        String portStr = skipPort ? "" : ":" + port;

        return scheme + "://" + request.getServerName() + portStr;
    }

    public static String getFolder(HttpServletRequest request) {
        String url = getUrl(request);
        return StringUtils.substringBeforeLast(url, "/");
    }

    public static String getArgInfo(ServletRequest request) {
        Map<String, String[]> parameterMap = request.getParameterMap();
        if (!parameterMap.isEmpty()) {
            StringBuilder sb = new StringBuilder();
            for (Entry<String, String[]> e : parameterMap.entrySet()) {
                sb.append(e.getKey()).append("=");

                if (e.getValue() != null) {
                    for (String v : e.getValue()) {
                        sb.append(v).append(",");
                    }
                    sb.deleteCharAt(sb.length() - 1);
                }
                sb.append("\r\n");
            }

            sb.deleteCharAt(sb.length() - 1);
            return sb.toString();
        }
        return null;
    }

    public static String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        log.debug("X-Forwarded-ForIP{}", ip);
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
            log.trace("Proxy-Client-IP代理IP{}", ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
            log.trace("WL-Proxy-Client-IP代理IP{}", ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
            log.trace("HTTP_CLIENT_IP{}", ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            log.trace("HTTP_X_FORWARDED_FOR{}", ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
            log.trace("getRemoteAddr{}", ip);
        }

        // 如果是多级代理，那么取第一个ip为客户ip
        if (ip != null && ip.contains(",")) {
            ip = ip.substring(ip.lastIndexOf(",") + 1).trim();
        }

        if (ip == null) {
            return null;
        }

        return ip.equals("0:0:0:0:0:0:0:1") ? "127.0.0.1" : ip;
    }

    public static String getUserAgent(HttpServletRequest request) {
        return request.getHeader("User-Agent");
    }

    public static HttpServletRequest currentRequest() {
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        if (sra != null) {
            return sra.getRequest();
        }
        return null;
    }

    public static boolean isJson(HttpServletRequest request, Object handler) {
        if (handler instanceof HandlerMethod) {
            HandlerMethod method = (HandlerMethod) handler;
            Annotation[] oAnn = method.getBean().getClass().getAnnotations();
            for (Annotation ann : oAnn) {
                if (ann instanceof RestController) {
                    return true;
                }
            }

            Annotation[] mAnn = method.getMethod().getAnnotations();
            for (Annotation ann : mAnn) {
                if (ann instanceof ResponseBody) {
                    return true;
                }
            }
        }

        return isAjax(request);
    }

    public static boolean isAjax(HttpServletRequest request) {
        String xRequestWith = request.getHeader("X-Requested-With");
        return xRequestWith != null && xRequestWith.equals("XMLHttpRequest");

    }

    public static boolean isIP(String server) {
        String regex = "[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}";
        boolean matches = Pattern.matches(regex, server);
        return matches;
    }

    public static <T> T setAttr(String key, T obj) {
        currentRequest().setAttribute(key, obj);
        return obj;
    }

    public static <T> T getAttr(String key) {
        HttpServletRequest httpServletRequest = currentRequest();
        Assert.state(httpServletRequest != null, "非http请求");
        return (T) httpServletRequest.getAttribute(key);
    }

}
